/*
 * COPYRIGHT. ShenZhen JiMi Technology Co., Ltd. 2017.
 * ALL RIGHTS RESERVED.
 *
 * No part of this publication may be reproduced, stored in a retrieval system, or transmitted,
 * on any form or by any means, electronic, mechanical, photocopying, recording, 
 * or otherwise, without the prior written permission of ShenZhen JiMi Network Technology Co., Ltd.
 *
 * Amendment History:
 * 
 * Date                   By              Description
 * -------------------    -----------     -------------------------------------------
 * 2017年4月14日    li.shangzhi         Create the class
 * http://www.jimilab.com/
 */

package com.jimi.web.api.impl;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.jimi.dto.base.ApiResult;
import com.jimi.framework.annotation.filter.ReqFilter;
import com.jimi.framework.annotation.log.LoggerProfile;
import com.jimi.framework.base.BaseApi;
import com.jimi.framework.bean.BeanUtil;
import com.jimi.framework.utils.UUIDGenerator;
import com.jimi.web.api.IDevicesApiService;
import com.jimi.web.comm.DeviceLocationInfo;
import com.jimi.web.dto.input.ElectricFenceInputDto;
import com.jimi.web.dto.output.DeviceInfoOutputDto;
import com.jimi.web.dto.output.DeviceLocationInfoOutputDto;
import com.jimi.web.dto.output.GpsPointOutputDto;
import com.jimi.web.model.Device;
import com.jimi.web.model.DeviceMcType;
import com.jimi.web.model.ElectricFence;
import com.jimi.web.model.GpsPoint;
import com.jimi.web.service.IDeviceService;
import com.jimi.web.service.IFenceService;
import com.jimi.web.service.IUserService;
import com.jimi.web.util.CmdAPIContent;
import com.jimi.web.util.CmdUtil;
import com.jimi.web.util.DeviceUtil;
import com.jimi.web.util.EelctricFenceCode;
import com.jimi.web.util.Globals.DeviceToCode;
import com.jimi.web.util.TrackApiUtils;
import com.jimi.web.util.map.BaidutoGps;
import com.jimi.web.util.map.Point;

/**
 * @FileName DevicesApiServiceImpl.java
 * @Description:
 *
 * @Date 2017年4月14日 上午9:48:05
 * @author li.shangzhi
 * @version 1.0
 */
@Service
public class DevicesApiServiceImpl extends BaseApi implements IDevicesApiService {

	@Resource
	private IUserService userService;

	@Resource
	private IDeviceService deviceService;

	@Resource
	private IFenceService fenceService;

	@Value("${language}")
	private String language;

	@Override
	@LoggerProfile(methodNote = "IDevicesApiService.getLocations")
	public List<DeviceLocationInfoOutputDto> getLocations(String imeis, String mapType) {
		List<Device> deviceList = deviceService.getDevice(imeis);
		if (null != deviceList && !deviceList.isEmpty()) {
			List<DeviceLocationInfo> infoLst = DeviceUtil.getDeviceLocationInfo(deviceList, mapType, language);
			return (List<DeviceLocationInfoOutputDto>) BeanUtil.convertBeanList(infoLst, DeviceLocationInfoOutputDto.class);
		}
		return Collections.emptyList();
	}

	@Override
	@LoggerProfile(methodNote = "IDevicesApiService.getTracks")
	public List<GpsPointOutputDto> getTracks(String imei, String beginTime, String endTime, String mapType) {
		List<GpsPoint> gpsPoints = TrackApiUtils.getTrack(imei, beginTime, endTime);
		if (null != gpsPoints && !gpsPoints.isEmpty()) {
			if ("BAIDU".equals(mapType)) {
				for (GpsPoint gps : gpsPoints) {
					Point bdPoint = BaidutoGps.gps84_To_gcj02(gps.getLat(), gps.getLng());
					bdPoint = BaidutoGps.gcj02_to_bd09(bdPoint.getLat(), bdPoint.getLng());

					gps.setLat(bdPoint.getLat());
					gps.setLng(bdPoint.getLng());
				}
				return (List<GpsPointOutputDto>) BeanUtil.convertBeanList(gpsPoints, GpsPointOutputDto.class);
			}
			if ("GOOGLE".equals(mapType)) {
				if ("zh".equals(language)) {
					for (GpsPoint gps : gpsPoints) {
						Point bdPoint = BaidutoGps.gps84_To_gcj02(gps.getLat(), gps.getLng());
						gps.setLat(bdPoint.getLat());
						gps.setLng(bdPoint.getLng());
					}
					return (List<GpsPointOutputDto>) BeanUtil.convertBeanList(gpsPoints, GpsPointOutputDto.class);
				} else {
					// 直接返回原始gps
					return (List<GpsPointOutputDto>) BeanUtil.convertBeanList(gpsPoints, GpsPointOutputDto.class);
				}
			}
			// 直接返回原始gps
			return (List<GpsPointOutputDto>) BeanUtil.convertBeanList(gpsPoints, GpsPointOutputDto.class);
		}
		return Collections.emptyList();
	}

	@Override
	@LoggerProfile(methodNote = "IDevicesApiService.bindUser")
	public boolean bindUser(String imei, String bindUserId, String bindAccount) {
		String orgId = userService.getDefaultUserGroupId(bindUserId);
		Device d = new Device();
		d.setImei(imei);
		d.setBindUserId(bindUserId);
		d.setBindUserAccount(bindAccount);
		d.setBindUserOrgId(orgId);
		deviceService.updateEquipment(d);
		// bindTrackDevice(userId, imei); // 修改DC的绑定状态
		deviceService.updateBind(imei, "1");
		logger.info("将设备：{}绑定到用户：{}上", imei, bindUserId);
		return true;
	}

	@Override
	@LoggerProfile(methodNote = "IDevicesApiService.unBindUser")
	public boolean unBindUser(String imei, String userId) {
		Device d = new Device();
		d.setImei(imei);
		d.setBindUserId(null);
		d.setBindUserAccount(null);
		d.setOrgId(null);
		deviceService.updateEquipment(d);
		// bindTrackDevice(userId, imei); // 修改DC的绑定状态
		deviceService.updateBind(imei, "0");
		logger.info("将用户：{}的设备：{}解除绑定。", userId, imei);
		return true;
	}

	@Override
	@LoggerProfile(methodNote = "IDevicesApiService.updateDeviceInfo")
	public String updateDeviceInfo(String imei, String deviceName, String vehicleName, String vehicleIcon, String vehicleNumber,
			String vehicleModels, String driverName, String driverPhone) {
		Device d = new Device();
		d.setImei(imei);
		d.setDeviceName(deviceName);
		d.setVehicleName(vehicleName);
		d.setVehicleIcon(vehicleIcon);
		d.setVehicleNumber(vehicleNumber);
		d.setVehicleModels(vehicleModels);
		d.setDriverName(driverName);
		d.setDriverPhone(driverPhone);
		// deviceService.updateEquipment(d);
		// deviceService.updateEquipmentDetail(d);
		return TrackApiUtils.updateEquipment(d);
	}

	@Override
	@LoggerProfile(methodNote = "IDevicesApiService.checkDeviceRange")
	public DeviceInfoOutputDto checkDeviceRange(String userId, String imei) {
		Device device = deviceService.checkDeviceRange(userId, imei);
		if (null == device) {
			logger.info("userId：{}下没有该设备，imei：{}", userId, imei);
			return null;
		}
		return (DeviceInfoOutputDto) BeanUtil.convertBean(device, DeviceInfoOutputDto.class);
	}

	@Override
	@LoggerProfile(methodNote = "IDevicesApiService.createElectricFence")
	public ApiResult createElectricFence(ElectricFenceInputDto electricFenceInputDto) {
		List<ElectricFence> electricFenceList = fenceService.getElectricFenceByImei(electricFenceInputDto.getImei());
		if (null != electricFenceList && electricFenceList.size() > 0) {
			for (ElectricFence electricFence : electricFenceList) {
				if (electricFence.getName().equals(electricFenceInputDto.getFenceName().trim())) {
					// 围栏名称已存在
					ApiResult apiResult = new ApiResult();
					apiResult.setResultCode(EelctricFenceCode.YES_GEOZONE);
					apiResult.setResultMsg("围栏名已存在");
					logger.info("围栏名已存在，围栏名：{}", electricFence.getName());
					return apiResult;
				}
			}
		}

		DeviceMcType bo = deviceService.getDeviceDictByTypy(electricFenceInputDto.getMcType());
		String ext1 = bo.getExt1();// 是否支持离线指令；0：否、1：是
		String ext5 = bo.getExt5();// 单围栏、多围栏；1：单围栏、N：多围栏
		String ext6 = bo.getExt6();// 多围栏个数
		if (ext5.equals("1")) {
			if (null != electricFenceList && electricFenceList.size() > 0) {
				ApiResult apiResult = new ApiResult();
				apiResult.setResultCode(EelctricFenceCode.MORE_THAN_SET_NUMBER);
				apiResult.setResultMsg("超过机型支持围栏数");
				logger.info("超过机型支持围栏数，当前围栏数：{}", electricFenceList.size());
				return apiResult;// 围栏个数已满
			}
		}
		if (ext5.equals("N")) {
			if (electricFenceList.size() >= Integer.valueOf(ext6)) {
				// 围栏个数已满
				ApiResult apiResult = new ApiResult();
				apiResult.setResultCode(EelctricFenceCode.MORE_THAN_SET_NUMBER);
				apiResult.setResultMsg("超过机型支持围栏数");
				logger.info("超过机型支持围栏数，当前围栏数：{}", electricFenceList.size());
				return apiResult;// 围栏个数已满
			}
		}

		ElectricFence electricFence = new ElectricFence();
		if (ext5.equals("N")) {
			// electricFence.setInstructNo(String.valueOf(electricFenceList.size()
			// + 1));//设置序号
			electricFence.setInstructNo(getInstructNo(electricFenceList));
		} else {
			electricFence.setInstructNo("1"); // 设置序号
		}
		electricFence.setImei(electricFenceInputDto.getImei());
		electricFence.setName(electricFenceInputDto.getFenceName());
		electricFence.setAlarmType(electricFenceInputDto.getAlarmType());
		electricFence.setRadius(electricFenceInputDto.getRadius());
		electricFence.setReportMode(electricFenceInputDto.getReportMode());
		if (StringUtils.isBlank(electricFenceInputDto.getMapType())) {
			electricFence.setMapType("BAIDU"); // 默认baidu
		} else {
			electricFence.setMapType(electricFenceInputDto.getMapType());
		}
		electricFence.setZoomLevel(electricFenceInputDto.getZoomLevel());
		electricFence.setCoordinate1(electricFenceInputDto.getLat() + "," + electricFenceInputDto.getLng());

		double lat = Double.valueOf(electricFenceInputDto.getLat().trim());
		double lng = Double.valueOf(electricFenceInputDto.getLng().trim());
		Point gpsPoint;
		if ("BAIDU".equals(electricFence.getMapType())) {
			gpsPoint = BaidutoGps.bd09_to_gcj02(lat, lng);
			gpsPoint = BaidutoGps.gcj02_To_gps84(gpsPoint.getLng(), gpsPoint.getLat());
		} else {
			if ("zh".equals(language)) {
				// 国内都是gcj-02坐标
				gpsPoint = BaidutoGps.gcj02_To_gps84(lng, lat);
			} else {
				// 国外直接是原始坐标
				gpsPoint = new Point(lng, lat);
			}
		}
		electricFence.setCoordinate2(lat + "," + lng);
		electricFence.setGpsCoordinate(gpsPoint.getLng() + "," + gpsPoint.getLat());

		CmdAPIContent ctx = CmdUtil.sendInstruct(electricFence, ext5, electricFenceInputDto.getAlarmSwitch(), "ON");
		// 由于离线指令存在覆盖问题，暂不支持离线指令，所有支持离线指令的设备均返回"设备部不在线"
		if (ctx.getCode() == DeviceToCode.CommandsDevice_NONET) {
			ApiResult apiResult = new ApiResult();
			apiResult.setResultCode(EelctricFenceCode.DEVICE_NONET);
			apiResult.setResultMsg("设备不在线，无法创建电子围栏");
			logger.info("设备不在线，无法创建电子围栏。设备imei：{}", electricFenceInputDto.getImei());
			return apiResult;
		}
		if (ctx.getCode() != DeviceToCode.Command_execution_success) {
			ApiResult apiResult = new ApiResult();
			apiResult.setResultCode(EelctricFenceCode.GEOZONE_ERROR);
			apiResult.setResultMsg(ctx.getMsg());
			logger.info("创建电子围栏操作失败。返回码：{}", ctx.getCode());
			return apiResult;// 没有成功，不入库
		}

		electricFence.setInstructCode(ctx.getCode());
		electricFence.setId(UUIDGenerator.get32LowCaseUUID());
		fenceService.insert(electricFence);
		logger.info("创建电子围栏操作成功。");
		ApiResult apiResult = new ApiResult();
		apiResult.setResultCode(0);
		apiResult.setResultMsg("创建电子围栏成功");
		apiResult.setResult(electricFence.getInstructNo());
		return apiResult;
	}

	@Override
	@LoggerProfile(methodNote = "IDevicesApiService.deleteElectricFence")
	public ApiResult deleteElectricFence(String imei, String mcType, String instructNo) {
		ElectricFence electricFence = fenceService.getElectronicFenceByNo(imei, instructNo);
		DeviceMcType bo = deviceService.getDeviceDictByTypy(mcType);
		String ext5 = bo.getExt5();// 单围栏、多围栏；1：单围栏、N：多围栏

		CmdAPIContent ctx = CmdUtil.sendInstruct(electricFence, ext5, "OFF", "OFF");
		// 由于离线指令存在覆盖问题，暂不支持离线指令，所有支持离线指令的设备均返回"设备部不在线"
		if (ctx.getCode() == DeviceToCode.CommandsDevice_NONET) {
			ApiResult apiResult = new ApiResult();
			apiResult.setResultCode(EelctricFenceCode.DEVICE_NONET);
			apiResult.setResultMsg("设备不在线，无法删除电子围栏");
			logger.info("设备不在线，无法删除电子围栏。设备imei：{}", imei);
			return apiResult;
		}
		if (ctx.getCode() != DeviceToCode.Command_execution_success) {
			ApiResult apiResult = new ApiResult();
			apiResult.setResultCode(EelctricFenceCode.GEOZONE_ERROR);
			apiResult.setResultMsg(ctx.getMsg());
			logger.info("删除电子围栏操作失败。返回码：{}", ctx.getCode());
			return apiResult;// 没有成功，不删除
		}
		fenceService.delete(electricFence.getId());
		logger.info("删除电子围栏操作成功。");
		ApiResult apiResult = new ApiResult();
		apiResult.setResultCode(0);
		apiResult.setResultMsg("删除电子围栏成功");
		return apiResult;
	}

	/**
	 * 获取指令序列号
	 * 
	 * @param electricFence
	 * @param ext6
	 * @return
	 */
	private String getInstructNo(List<ElectricFence> list) {
		String serialNumber = "";
		Map<String, ElectricFence> map = new HashMap<String, ElectricFence>();
		for (ElectricFence ef2 : list) {
			map.put(ef2.getInstructNo(), ef2);
		}
		for (int i = 1; i <= map.size(); i++) {
			if (null == map.get(i + "")) {
				serialNumber = i + "";
				break;
			}
		}
		if (StringUtils.isEmpty(serialNumber)) {
			serialNumber = (list.size() + 1) + "";
		}
		return serialNumber;
	}

	@Override
	@ReqFilter(keySpel = "'moveDevice_'+#srcUserId+'_To_'+#destUserId+'_'+#imeis", limit = 1, time = 10000)
	@LoggerProfile(methodNote = "IDevicesApiService.moveDevice")
	public String moveDevice(String srcUserId, String destUserId, String imeis) {
		String code = TrackApiUtils.moveEuipment(srcUserId, destUserId, imeis);
		logger.info("转移/销售设备操作完成，返回码：{}", code);
		return code;
	}
}
